local GameDB = class("GameDB")

local C_getCacheValue  = cc.TableCache.getCacheValue
local C_getCacheValues  = cc.TableCache.getCacheValues
local C_removeAllCache  = cc.TableCache.removeAllCache
local C_addCache  = cc.TableCache.addCache
local C_getCache  = cc.TableCache.getCache

local string_find = string.find
local string_split = string.split
local math_random = math.random
local table_insert = table.insert
local table_remove = table.remove
local table_concat = table.concat

function GameDB:ctor()

end

function GameDB:removeAllCache()
    C_removeAllCache()
end

function GameDB:reloadCache(name, keyName)
    C_addCache(name)
end

-- 获得的是{key=Row, ...} 的 key-value table
function GameDB:getCachedTable(name,order)
    local ret = C_getCache(name)
    if ret then
        if type(order)=="function" then
            table.sort(ret, order)
        end
    end
    return ret
end

-- 获得 Row
function GameDB:getCachedValue(name,keyOrFilter)
    if not keyOrFilter then
        return nil
    end

    local ret = C_getCacheValue(name, keyOrFilter)
    return ret
end

-- 获得的是{Row, Row} 的 数组table
function GameDB:getCachedValues(name,filter,order)
    local ret = C_getCacheValues(name, filter)
    if type(order)=="function" then
        table.sort(ret,order)
    end
    return ret
end

function GameDB:getSystemPar(k,default)
    local res = self:getCachedValue("globalpars",k)
    if not res then
        return (default and default or k)
    end
    return res.par
end

function GameDB:getSystemStrPar(k,default)
    local res = self:getCachedValue("globalpars",k)
    if not res then
        return (default and default or k)
    end
    return res.strPar
end

function GameDB:getBagConfs()
    return self:getCachedValues("bag")
end

function GameDB:getBagConfById( bagId )
    return self:getCachedValue("bag",bagId)
end

function GameDB:getDailyReardById(id)
    return self:getCachedValue("dailyWeeklyRewards",id)
end

function GameDB:getDailyBlessRewardByLev(lev)
    local conf = self:getCachedValue("dailyWeeklyRewards",lev)
    if conf then
        return conf.blessingReward
    end
end

function GameDB:queryAuctionshopSubKey(id)
    return self:getCachedValue("auctionshop_subkey",id)
end

function GameDB:queryAuctionshopTypeList(type)
    return self:getCachedValue("auctionshop_subkey",function(v)
        return v.type==type
    end)
end

function GameDB:queryAuctionshop()
	local res = self:getCachedValues("auctionshop",nil,function(l,r)
        return tonumber(l.ID) < tonumber(r.ID)
    end)
	return res
end

function GameDB:queryAuctionshopById(id)
	local res = self:getCachedValue("auctionshop",id)
	return res
end

function GameDB:queryProBase(tid)
	local res = self:getCachedValue("player_base",tid)
	return res
end

function GameDB:querypropShowById(tid)
    local res = self:getCachedValue("propShow",tid)
    return res
end

function GameDB:querypropShow()
    return self:getCachedValues("propShow",nil,function(l,r)
        return tonumber(l.ID) < tonumber(r.ID)
    end)
end

function GameDB:querypropExtraByPropIDandQuality( propID, quality )
    local id = tostring(propID)
    local qualitystr = tostring(quality)
    return self:getCachedValue("prop_extra",function(v)
        return v.propID==id and v.quality==qualitystr
    end)
end

function GameDB:queryDrop(id)
	local res = self:getCachedValue("drop",id)
	return res
end

function GameDB:queryStatistics()
    return self:getCachedValues("statistics",nil,function(l,r)
        return tonumber(l.ID) < tonumber(r.ID)
    end)
end

function GameDB:queryNpc(npcID)
    -- return self:getCachedValue("bnpc",npcID)
    return self:getCachedValue("bnpc2",npcID)
end

function GameDB:queryBNpcs()
    return self:getCachedTable("bnpc2")
end

function GameDB:queryNpcRes(npcID)
    return self:getCachedValue("npc_res",npcID)
end

function GameDB:queryMerc(mercID)
    --TODO mercenary 表没有了需要重新设计
    return nil
end

function GameDB:queryMercRes(mercID)
    --TODO mercenary_res 表没有了需要重新设计
    return nil
end

function GameDB:queryMercenaryRaceById(raceId)
    --TODO mercenary_race 表没有了需要重新设计
    return nil
end

function GameDB:queryItems()
    return self:getCachedValues("item")
end

function GameDB:queryJewels()
    return self:getCachedValues("jewel2")
end

function GameDB:getJewelMastersByClass(classId)
    --根据职业id获取相关的宝石评分等级信息
    return self:getCachedValues("jewel_master",
        --filter
        function(v)
            return v.class == tostring(classId)
        end,
        --oder
        function(l,r)
            return tonumber(l.ID) < tonumber(r.ID)
        end)
end


function GameDB:getToolConfig(toolId)
    return self:getCachedValue("tool",toolId)
end

function GameDB:getToolResConfig(toolId)
    return self:getCachedValue("tool_res",toolId)
end

function GameDB:getAllToolConfigByType(mainType)
    return self:getCachedValues("tool",
        --filter
        function(v)
            return v.mainType == tostring(mainType)
        end,
        --oder
        function(l,r)
            return tonumber(l.quality) < tonumber(r.quality)
        end)
end

function GameDB:getAllToolResByType(type)
    local tools = self:getAllToolConfigByType(type)
    local ret = {}
    for _,v in ipairs(tools) do
        table.insert(ret,self:getCachedValue("tool_res",v.ID))
    end
    return ret
end

function GameDB:getAllToolTypeConfig()
    return {1,2,3}
end

-- 废弃
-- function GameDB:getAllCoins()
--     local coinConfig = self:getCachedTable("coins_res")
--     return coinConfig
-- end

function GameDB:getCoinConfig(id)
    local coinConfig = self:getCachedValue("coins_res",id)
    return coinConfig
end

function GameDB:getTalentAffixConfig(id)
    assert(false,"表格已废弃请重新实现") --@ignore
    return nil
end

-- 获得配方配置
--
function GameDB:getFormulaConfig(formulaId)
    if not formulaId then
        return nil
    end
    local formulaConfig = self:getCachedValue("formula",formulaId)
    if not formulaConfig then
        formulaConfig = self:getCachedValue("formula",711001)
    end
    return formulaConfig
end

function GameDB:getFormulaByType(t)
    local formulaConfig = self:getCachedValues("formula",function(v)
        return v.type==tostring(t)
    end)
    return formulaConfig
end

function GameDB:getFormulaByTypeLevel(t, level)
    --string.format("SELECT * FROM formula WHERE type = %d AND value1 <= %d AND value1 > 0", t, compoundLabLevel)
    return self:getCachedValues("formula",function(v)
        if v.type==tostring(t) then
            local lv = tonumber(v.value1) or -1
            if lv > 0 and lv <= tonumber(level) then
                return true
            end
        end
        return false
    end)
end
--战斗经验疲劳段
function GameDB:getBattleExpLimit(level)
    local buffLimitConfig = self:getCachedValue("battle_exp_limit",level)
    return buffLimitConfig
end


function GameDB:getBuffConfig(buffId)
    if not buffId then
        return nil
    end
    local buffConfig = self:getCachedValue("mapbuff",buffId)
    if not buffConfig or not buffConfig.ID then
        buffConfig = self:queryMapbuffShowById(buffId)
    end
    return buffConfig
end

function GameDB:queryMapbuffShowById(id)
    return self:getCachedValue("mapbuff_show",id)
end

function GameDB:queryFightingLv(team,lv)
    assert(false,"fighting_lv表已废弃") --@ignore
end 

function GameDB:queryStoneById(stoneId)
    assert(false,"stone表已废弃") --@ignore
end

-- 通过 dungeonId 取具体副本配置
function GameDB:queryDungeonCfgById( dungeonId )
    local dungeonConf = self:getCachedValue( "dungeon_total", tonumber( dungeonId ) )
    return dungeonConf
end

function GameDB:queryDungeonConfigs()
    return self:getCachedTable("dungeon_total")
end

function GameDB:queryMapNpc(npcId)
	if not npcId then return nil end

	local npcConfig = self:getCachedValue("mapset_base",npcId)
	if not npcConfig then
		npcConfig = self:getCachedValue("mapset_show",npcId)
		if not npcConfig then
            npcConfig = self:getCachedValue("ore",npcId)
		end
	end

	return npcConfig
end

function GameDB:queryMapsetBaseByMapId(mapId)
    local configs = self:getCachedValues("mapset_base",function(v)
        return tonumber(v.mapId) == mapId
    end)
    return configs
end

function GameDB:queryMapsetShowById(npcId)
    local config = self:getCachedValue("mapset_show", npcId)
    return config
end

function GameDB:queryMapsetShowByMapId(mapId)
    local configs = self:getCachedValues("mapset_show",function(v)
        return tonumber(v.mapId) == mapId
    end)
    return configs
end

function GameDB:queryMapsetOpenTaskNpcs()
    return self:getCachedValues("mapset_opentask")
end

-- function GameDB:queryMapsetRandomByMapId(mapId)
--     local configs = self:getCachedValues("mapset_random",function(v)
--         return tonumber(v.mapId) == mapId
--     end)
--     return configs
-- end

-- function GameDB:queryMapsetRandomByTrackQuest()
--     local configs = self:getCachedValues("mapset_random",function(v)
--         return tonumber(v.trackQuest) ~= nil
--     end)
--     return configs
-- end

function GameDB:queryOreConfigById(oreId)
    local oreConfig = self:getCachedValue("ore",oreId)
    return oreConfig
end

function GameDB:queryOreByType(oType)
    local configs = self:getCachedValues("ore",function(v)
        return tonumber(v.type) == oType
    end)
    return configs
end

function GameDB:queryOreByMapId(mapId)
    local configs = self:getCachedValues("ore",function(v)
        return tonumber(v.mapId) == mapId
    end)
    return configs
end

function GameDB:queryNearbyOreIdByType(oType,mapId,ox)
    local npcId = nil
    local tempX = 0
    local configs = self:queryOreByMapId(mapId)
    for k,v in pairs(configs) do
        if tonumber(v.refreshType) == 1 and tonumber(v.type) == oType then
            local px = tonumber(v.coordinate)
            if px then
                local disx = math.abs(px - ox)
                if tempX > disx then
                    tempX = disx
                    npcId = tonumber(v.ID)
                elseif tempX == 0 then
                    tempX = disx
                    npcId = tonumber(v.ID)
                end
            end
        end
    end
    return npcId
end

function GameDB:queryNearbyNpcIdByFunction(fId,mapId,ox)
    local npcId = nil
    local tempX = 0

    local configs = self:queryMapsetBaseByMapId(mapId)
    for _,v in pairs(configs) do
        if tonumber(v["function"]) == fId then
            local px = tonumber(v.coordinate)
            if px then
                local disx = math.abs(px - ox)
                if tempX > disx then
                    tempX = disx
                    npcId = tonumber(v.ID)
                elseif tempX == 0 then
                    tempX = disx
                    npcId = tonumber(v.ID)
                end
            end
        end
    end
    configs = self:queryMapsetShowByMapId(mapId)
    for _,v in pairs(configs) do
        if tonumber(v["function"]) == fId then
            local px = tonumber(v.coordinate)
            if px then
                local disx = math.abs(px - ox)
                if tempX > disx then
                    tempX = disx
                    npcId = tonumber(v.ID)
                elseif tempX == 0 then
                    tempX = disx
                    npcId = tonumber(v.ID)
                end
            end
        end
    end
    return npcId
end

-- function GameDB:queryRandomNearbyNpcIdByMapId(mapId,ox)
--     local npcId = nil
--     local tempX = 0
--     local configs = self:queryMapsetRandomByMapId(mapId)
--     for _,v in pairs(configs) do
--         local px = tonumber(v.coordinate)
--         if px then
--             local disx = math.abs(px - ox)
--             if tempX > disx then
--                 tempX = disx
--                 npcId = tonumber(v.ID)
--             elseif tempX == 0 then
--                 tempX = disx
--                 npcId = tonumber(v.ID)
--             end
--         end
--     end
--     return npcId
-- end

-- function GameDB:getRandomNpcIdByTrackQuest()
--     local npcId = nil
--     local configs = self:queryMapsetRandomByTrackQuest()
--     local sortConfigs = {}
--     for k,v in pairs(configs) do
--         table.insert(sortConfigs,v)
--     end
--     table.sort(sortConfigs, function(a,b) return tonumber(a.trackQuest) > tonumber(b.trackQuest) end)

--     for k,v in pairs(sortConfigs) do
--         if UD:getCurTaskId() > tonumber(v.trackQuest) then
--             npcId = tonumber(v.ID)
--             break
--         end
--     end
--     return npcId
-- end


function GameDB:queryOreByMapIdAndType(mapId,oType)
    local configs = self:getCachedValues("ore",function(v)
        return (tonumber(v.mapId) == mapId and tonumber(v.type) == oType)
    end)
    return configs
end

function GameDB:formatIconFilePath(bagType,iconName)
	local iconPath = nil
	local suffix = "png"
	local path = Res.itemPath
	if bagType == Enums.ItemBagType.item then
		path = Res.itemPath
	elseif bagType == Enums.ItemBagType.mount then
		path = Res.mountIconPath
	elseif bagType == Enums.ItemBagType.daibi then
        path = Res.coinIconPath
	elseif bagType == Enums.ItemBagType.tool then
		path = Res.itemPath
	elseif bagType == Enums.ItemBagType.mercenary then
		path = Res.mercenaryIconPath
	elseif bagType == Enums.ItemBagType.making then
	elseif bagType == Enums.ItemBagType.equip then
		path = Res.weaponResPath
	elseif bagType == Enums.ItemBagType.mask then
		path = Res.maskIconPath
	elseif bagType == Enums.ItemBagType.jewel then
		path = Res.jewelIconPath
	end

	if iconName then
		iconPath = string.format("%s%s.%s",path,iconName,suffix)
	end

	return iconPath
end


function GameDB:getItemIconFile(bagType,tid)
	local iconName = nil
	local suffix = "png"
	local path = Res.itemPath
	if bagType == Enums.ItemBagType.item then
        local config = self:queryItemById(tid) or {}
		iconName = config.icon
	elseif bagType == Enums.ItemBagType.equip then
		path = Res.weaponResPath
        local config = self:getEquipResConf(tid) or {}
		iconName = config.icon
	elseif bagType == Enums.ItemBagType.mount then
		path = Res.mountIconPath
        local config = self:getMountResConfig(tid) or {}
		iconName = config.icon
	elseif bagType == Enums.ItemBagType.jewel then
		path = Res.jewelIconPath
        local config = self:queryJewelById(tid) or {}
		iconName = config.icon
	elseif bagType == Enums.ItemBagType.mercenary then
		iconName = self:queryMercRes(tid).icon
    elseif bagType == Enums.ItemBagType.daibi then
        path = Res.coinIconPath
        iconName = self:getCoinConfig(tid).icon
    elseif bagType == Enums.ItemBagType.tool then
        path = Res.itemPath
        local config = self:getToolResConfig(tid) or {}
        iconName = config.icon
    else
        local config = self:queryItemById(tid) or {}
		iconName = config.icon
	end

	if iconName then
		iconName = string.format("%s%s.%s",path,iconName,suffix)
	end

	return iconName
end

function GameDB:getNpcSfxPath(npcId)
    local npcRes = self:queryNpcRes(npcId)
    if not npcRes then
        return nil
    end
    local armaturePath = npcRes.dbRes
    if not armaturePath then
       return nil
    end
    local sfxPath = armaturePath
    --print("--------sfxPath:",sfxPath)
    local path = "sfx/"..sfxPath
    return path
end

function GameDB:getNpcDeathSound(npcId)
    local npcRes = self:queryNpcRes(npcId)
    if not npcRes then
        return nil
    end
    local soundFile = npcRes.deathSound
    if not soundFile then
       return nil
    end
    local path = "sfx/"..soundFile
    return path
end

function GameDB:getSelectSize(npcId)
    local npcRes = self:queryNpcRes(npcId)
    if not npcRes then
        return nil
    end
    local selectSize = npcRes.selectSize
    return selectSize or 100
end

function GameDB:getSelectExcursion(npcId)
    local npcRes = self:queryNpcRes(npcId)
    if not npcRes then
        return nil
    end
    local selectExcursion = npcRes.selectExcursion
    return selectExcursion or 0
end

function GameDB:getIsShowMana(npcId)
    local npcRes = self:queryNpcRes(npcId)
    if not npcRes then
        return nil
    end
    local showMana = npcRes.showMana
    if showMana and tonumber(showMana) == 1 then
       return true
    end
    return false
end

function GameDB:getItemName(itemBagType,tid)
	local name = nil
	if itemBagType == Enums.ItemBagType.item then
        local config = self:queryItemById(tid) or {}
		name = config.name
	elseif itemBagType == Enums.ItemBagType.equip then
        local config = self:getEquipConf(tid) or {}
		name = config.string
	elseif itemBagType == Enums.ItemBagType.jewel then
        local config = self:queryJewelById(tid) or {}
		name = config.name
	elseif itemBagType == Enums.ItemBagType.mask then
		--TODO
	elseif itemBagType == Enums.ItemBagType.mount then
        local config = self:getMountConfig(tid) or {}
		name = config.name
	else
        local config = self:queryItemById(tid) or {}
		name = config.name
	end

	return name
end

-- 获取表情配置
function GameDB:getEmojiConfs()
    local confs = self:getCachedValues("chat_res", nil, function(l,r)
            return tonumber(l.ID) < tonumber(r.ID)
        end)
    return confs
end

GameDB._transformTargetJewelIdsDict = {}
function GameDB:queryTransformTargetJewelIds(class, quality, lv)
    local key = string.format("%s_%s_%s", class, quality, lv)
    local jewelIds = self._transformTargetJewelIdsDict[key]
    if not jewelIds then
        local jewels = self:getCachedValues("jewel2",
            function(v)
                return v.class==tostring(class) and
                        v.quality==tostring(quality) and
                        v.lv==tostring(lv)
            end,
            function(l,r)
                local tp_l = tonumber(l.type)
                local tp_r = tonumber(r.type)
                if tp_l == tp_r then
                    return tonumber(l.ID) < tonumber(r.ID)
                else
                    return tp_l < tp_r
                end
            end)

        jewelIds = {}
        for i,jewel in ipairs(jewels) do
            jewelIds[i] = tonumber(jewel.ID)
        end
        self._transformTargetJewelIdsDict[key] = jewelIds
    end
    return jewelIds
end

function GameDB:queryJewelLevelUpGrowLvCap(class,type,quality,attrType)
    local res = self:getCachedValues("jewel2",
    function(v)
        return  v.class==tostring(class) and
                v.type == tostring(type) and
                v.quality==tostring(quality) and
                v.attrType == tostring(attrType)
    end,
    function(l,r)
        return tonumber(l.lv) > tonumber(r.lv)
    end)
    return res[1] or {}
end

function GameDB:queryJewelByLevel(class,type,quality,attrType,level)
    local res = self:getCachedValue("jewel2",
    function(v)
        return  v.class==tostring(class) and
                v.type == tostring(type) and
                v.quality==tostring(quality) and
                v.attrType == tostring(attrType) and
                v.lv == tostring(level)
    end)
    return res
end

-- 取attrType类型的所有宝石
function GameDB:queryJewelByAttrType( attrType )
    local res = self:getCachedValue("jewel2",
    function(v)
        return  v.attrType == tostring(attrType)
    end)
    return res
end

function GameDB:queryJewelById(jewelId)
	local jewel = self:getCachedValue("jewel2",jewelId)
	return jewel
end

function GameDB:getJewelTransformCostConf(quality, lv)
    local conf = self:getCachedValue("jewelTransfer", function(v)
        return tonumber(v.quality) == quality and tonumber(v.lv) == lv
    end)
    return conf
end

function GameDB:getJewelUpCost()
    local jewel = self:getCachedTable("jewelupgradecost")
    return jewel
end


function GameDB:getWorldExpLockConf()
     return self:getCachedValues("worldexplock",nil,
        function(l,r)
            return tonumber(l.ID) < tonumber(r.ID)
        end)
end

function GameDB:getWorldExpLockConfById(id)
     return self:getCachedValue("worldexplock",id)
end

function GameDB:queryStanceAction(stanceId)
	-- return self:query("SELECT * FROM stance_action WHERE ID="..stanceId)[1]
    return self:getCachedValue("stance_action",stanceId) or {}
end

function GameDB:getSoundEffectPathById(id)
    local config = self:getCachedValue("sound_effect",id)
    local path = nil
    if config then
        path= config.path
    end
    if not path then return tostring(id) end

    local ret = path
    if string_find(path,"|") then
        local pathList = string.split(path,"|")
        ret = pathList[math_random(1,#pathList)]
    end
    return ret
end

function GameDB:queryFeatureOnById(featureId)
	local ret = self:getCachedValue("featureon",featureId)
	return ret
end

function GameDB:queryFeatureOn()
	local featuresConfig = self:getCachedTable("featureon") or {}
	return featuresConfig
end

--TODO 活动数据以后会从服务器协议获取在缓存到本地
function GameDB:queryWelfares()
    --local sql = string.format("SELECT * FROM welfare_total")
    return {}
end

function GameDB:queryWelfareByPos(position)
    --local sql = string.format("SELECT * FROM welfare_total WHERE position = " .. position)
    return {}
end

function GameDB:queryWelfareById(id)
    --local sql = string.format("SELECT * FROM welfare_total WHERE ID = " .. id)
    return {}
end

function GameDB:queryWelfareShowByLevel(level)
    --local sql = string.format("SELECT * FROM welfare_show WHERE minLevel <= %d and maxLevel >= %d",level,level)
    return {}
end

function GameDB:queryMapById(mapId)
    local map = self:getCachedValue("map",mapId)
	return map
end

function GameDB:getMedalIdFromMap(mapId)
    local mapConfig = self:queryMapById(mapId)
    local badgeShow = nil
    if mapConfig and mapConfig.ID then
        badgeShow = tonumber(mapConfig.badgeShow)
    end
    return badgeShow
end

function GameDB:queryMapByType(mapType)
    --string.format("SELECT * FROM map WHERE maptype = %d",mapType)
    return self:getCachedValue("map",function(v)
        return v.maptype==tostring(mapType)
    end)
end

function GameDB:queryBigmapById(id)
    --string.format("SELECT * FROM bigmap WHERE ID = %d",id)
    return self:getCachedValue("bigmap",id)
end

function GameDB:queryMineById(id)
    return self:getCachedValue("mine",id)
end

function GameDB:queryTaskById(id)
    local taskC = self:getCachedValue("task",id)
    return taskC or {}
end

function GameDB:queryTasks()
    return self:getCachedValues("task",nil,
        function(l,r)
            return tonumber(l.ID) < tonumber(r.ID)
        end)
end

function GameDB:queryMainTasksLessId(id)
    return self:getCachedValues("task",function(v)
        return tonumber(v.ID) < tonumber(id)
            and tonumber(v.type) == 0
    end)
end

function GameDB:queryPreMainTasks(id)
    local pairTasks = {}
    local tasks = self:queryTasks()
    for _, task in ipairs(tasks) do
        pairTasks[tonumber(task.ID)] = task
    end

    local preTasks = {}
    local curTaskId = 901010000
    while true do
        if curTaskId >= id then break end
        local curTask = pairTasks[curTaskId]
        if not curTask then break end

        table.insert(preTasks, curTask)

        local nextTasks = string.split(curTask.nextTask, ";")
        if #nextTasks == 1 then -- 只有一个后续任务
            curTaskId = tonumber(nextTasks[1])
        else
            local taskId = UD:getTaskBranchId(curTaskId)
            if not taskId then break end
            curTaskId = taskId
        end
    end

    return preTasks
end

function GameDB:queryMainBranchTaskConf(taskId)
    local key = tostring(taskId)
    return self:getCachedValue("branchTask_icon", function(v)
        return v.taskID == key
    end)
end

function GameDB:queryDailyQuestByGroup(group)
    local key = tostring(group)
    local ret = self:getCachedValues("daily_quest",function(v)
        return v.group == key
    end)
    return ret
end

function GameDB:queryDailyQuestById(questId)
    local config = self:getCachedValue("daily_quest",questId)
    return config
end

function GameDB:queryHeroLevelUpByLevel(level)
    local config = self:getCachedValue("player_levelup",level)
    return config
end

function GameDB:queryBattleNormalMusics()
    -- local sql = string.format("SELECT * FROM battle_music WHERE isBoss = %d",0)
    local configs = self:getCachedValues("battle_music",function(v)
        return tonumber(v.isBoss) == 0
    end)
    return configs
end

function GameDB:queryBattleBossMusics()
    -- local sql = string.format("SELECT * FROM battle_music WHERE isBoss = %d",1)
    local configs = self:getCachedValues("battle_music",function(v)
        return tonumber(v.isBoss) == 1
    end)
    return configs
end

function GameDB:queryShopById(shopId)
    --local sql = string.format("SELECT * FROM shop WHERE ID = %d",shopId)
    return self:getCachedValue("shop",shopId)
end

function GameDB:queryHeadResById(headId)
    local config = self:getCachedValue("hair_res",headId)
    return config
end

function GameDB:queryFaceResById(faceId)
    local config = self:getCachedValue("face_res",faceId)
    return config
end

function GameDB:getMessageConfig(key)
    return self:getCachedValue("message",key)
end

function GameDB:getMessageStr(key)
    if not key then return L("lua_code_text_459") end

    local res = self:getCachedValue("message",key)
    if not res then return L(key) end
    local msgId = res["msgId"]
    if not msgId then return L(key) end
    local message = L(msgId)
    if not message then return L(key) end
    return message
end


function GameDB:queryWalkthroughByLevel(level)
    --TODO 待新设计
    --local sql = string.format("SELECT * FROM walkthrough WHERE minLv <= %d AND maxLv >= %d",level,level)
    --local config = self:query(sql)
    --return config
    return {}
end

function GameDB:queryMailById(id)
    return self:getCachedValue("mail",id)
end

function GameDB:queryWeatherById(id)
    local config = self:getCachedValue("weather",id)
    return config
end

function GameDB:queryShopTotal()
    local configs = self:getCachedTable("shop_total")
    return configs
end

function GameDB:queryGoodById(id)
    local config = self:getCachedValue("goods",id)
    return config
end

-- 竞速副本奖励表
function GameDB:queryDungeonRaceModeById(id)
    local res = self:getCachedValue("dungeon_race_mode",id)
    return res
end

-- 活动副本奖励表
function GameDB:queryEventModeById(id)
    local res = self:getCachedValue("event_mode",id)
    return res
end

function GameDB:queryBattleById(formationId)
    --local sql = string.format("SELECT * FROM battle WHERE ID = " .. formationId)
    return self:getCachedValue("battle",formationId)
end

function GameDB:queryDungeon()
    --TODO 待新设计
    --local sql = string.format("SELECT * FROM dungeon")
    --local configs = self:query(sql)
    return nil
end

function GameDB:queryFunctionLevelup()
    --TODO 待新设计
    --local sql = string.format("SELECT * FROM function_levelup")
    --local configs = self:query(sql)
    --return configs
    return {}
end

function GameDB:queryPartners()
    local config = self:getCachedTable("partner")
    return config
end

function GameDB:queryPartnerById(id)
    local config = self:getCachedValue("partner",id)
    return config
end

function GameDB:getPartnerNpcIdByPartnerId(id,quality)
    local npcId
    local partnerC = self:queryPartnerById(id)
    if partnerC then
        local field = Enums.qualityCfg[quality] or Enums.qualityCfg[1]
        npcId = partnerC[field]
    end
    return npcId
end

function GameDB:getPartnerAnimationListByPartnerId(id)
    local animationList = {}
    local partnerC = self:queryPartnerById(id)
    if partnerC and nil ~= partnerC.showAct then
        animationList = string.split(partnerC.showAct, ";")
    end
    return animationList
end

function GameDB:queryItemById(id)
    local config = self:getCachedValue("item",id)
    return config
end

function GameDB:queryRockById(id)
    local config = self:getCachedValue("rock",id)
    return config
end

function GameDB:queryQualityCfgById(id)
    local config = self:getCachedValue("partner_quality",id)
    return config
end

function GameDB:queryRestrictedRewardShowById( rareId )
    local config = self:getCachedValue("restrictedreward_show",rareId)
    return config
end

function GameDB:queryAllRestrictedRewardShow()
    return self:getCachedValues("restrictedreward_show",nil,
        function(l,r)
            return tonumber(l.ID)<tonumber(r.ID)
        end)
end

function GameDB:queryFunctionNpcById(id)
    return self:getCachedValue("function_npc",id)
end

function GameDB:queryDungeonSubById(id)
    --local sql = string.format("SELECT * FROM dungeon_sub WHERE ID = " .. id)
    return self:getCachedValue("dungeon_sub",id)
end

function GameDB:queryDungeonSubByMapId(mapId)
    --local sql = string.format("SELECT * FROM dungeon_sub WHERE mapID = " .. mapId)
    local ret = self:getCachedValue("dungeon_sub",
        function(v)
            return v.mapID == tostring(mapId)
        end)
    return ret
end

function GameDB:randomNickName(maxLen)
    local nameConfig = self:getCachedValues("name")

    local midNames = {}
    local firstNames = {}
    local lastNames = {}
    for _,v in pairs(nameConfig) do
        if v.firstName then
            table.insert(firstNames,v.firstName)
        end
        if v.midName then
            table.insert(midNames,v.midName)
        end
        if v.lastName then
            table.insert(lastNames,v.lastName)
        end
    end

    local fistName = string.trim(firstNames[math_random(1,#firstNames)])
    local index = math_random(1,#lastNames)
    while lastNames[index] == firstName
    do
        index = math_random(1,#lastNames)
    end
    local lastName = string.trim(lastNames[index])

    local midName = ""
    if #midNames > 0 then
        midName = string.trim(midNames[math_random(1,#midNames)])
    end

    local name = fistName .. midName .. lastName
    local ulen = string.counting(name)
    if ulen > Constant.NICKNAME_MAX_LEN then
        if string.len(midName) > 0 then
            name = fistName .. lastName
        elseif string.len(lastName) > 0 then
            name = fistName
        end
    else
        local randNum = math_random(1,2)
        if randNum == 1 then
            name = fistName .. lastName
        else
            name = fistName .. midName .. lastName
        end
    end
    return name
end

function GameDB:spawnNpcByFormationId(battleId,originPos)

    local battle = self:getCachedValue("battle",battleId)
    local fieldSize = tonumber(battle.battlefieldSize) --战场大小
    local roledefaultlocation = tonumber(self:getSystemPar("roledefaultlocation",0)) --主角距离左边界的距离
    local initPos = tonumber(battle.initPos) --怪物5号位置距离右边界的距离
    local formation = self:getCachedValue("formation2",battle.formationID)
    local space = tonumber(formation.space) --怪物站位间距
    local screenScale = 1
    local map = MapManager:getMap()
    if cc.isAlive(map) then
        screenScale = 1 / map:getGroundScale(Constant.BattleGroundLineNumber)
    end

    if battle.roleSpecialLocation then
        roledefaultlocation = tonumber(battle.roleSpecialLocation)
    end

    local ret = {
        range = (fieldSize - initPos - roledefaultlocation) / Constant.BattleLogicToSceneScale * screenScale
    }

    for i = 1 ,9 do
        local npcId = formation["npc"..i]
        if npcId and npcId:len()>0 then
            local battlePos = (((i - 5) * space ) / Constant.BattleLogicToSceneScale * screenScale)
            local p = (originPos + battlePos)
            local res = self:queryNpcRes(npcId)
            if res then
                local zOrder = tonumber(res.size) + ((10 - i) * 1000)
                ret[i] = {npcId = npcId, pos = p, z = zOrder}
            end
        end
    end
    return ret
end

function GameDB:randomLoadingTips()
    local configs = self:getCachedValues("loadingtips")
    if #configs==0 then
        return ""
    end
    local index = math_random(1,#configs)
    local tip = L(configs[index].des,"loadingtips missing")
    return tip
end

function GameDB:randomLoadingImage(mapId)
    local configs = self:getCachedValues("loadingimages",
        function(v)
            return v.belongMap==tostring(mapId)
        end)

    if #configs==0 then
        return nil
    end
    local index = math_random(1,#configs)
    local image = configs[index].path
    return image
end

function GameDB:getAttributeModifyById(id)
    local res = self:getCachedValue("attribute_modify",id)
    return res
end

function GameDB:getWorldConfs()
    return self:getCachedValues( "world_map", nil, function( lhs, rhs )
        return tonumber(lhs.ID) < tonumber(rhs.ID)
    end)
end

function GameDB:getWorldConfById( mapId )
    return self:getCachedValue("world_map",mapId)
end

function GameDB:queryWorldZoneConfs()
    return self:getCachedValues("district_info")
end

function GameDB:getDistrictInfoById(id)
    return self:getCachedValue("district_info", id)
end

function GameDB:getLionRewardById( monsterId )
    return self:getCachedValue("lionheart_reward",monsterId)
end

-- 返回remind表配置
function GameDB:getRemindConfById( Id )
    return self:getCachedValue( "remind", Id )
end

-- 返回 level_preview 表全配置
function GameDB:getGamePlayPreViewConfs()
    return self:getCachedValues( "level_preview", nil, function( lhs, rhs )
        return tonumber(lhs.ID) < tonumber(rhs.ID)
    end)
end
-- 根据 id 返回 level_preview 表中项
function GameDB:getGamePlayPreViewConfById( id )
    return self:getCachedValue("level_preview", id)
end

-- 冠军赛 根据day返回当天的赛事信息
function GameDB:queryThroneByDay(day)
    local config = self:getCachedValue("throne", day)
    return config
end

-- 冠军赛
function GameDB:getThronePar(k)
    local configs = self:getCachedValues("throneConfig")
    for _, value in ipairs(configs) do
        if value.thronePar == k then
            return value.par
        end
    end
    return k
end

-- 冠军赛
function GameDB:getThroneStrPar(k)
    local configs = self:getCachedValues("throneConfig")
    for _, value in ipairs(configs) do
        if value.thronePar == k then
            return value.strPar
        end
    end
    return k
end

-- 挑战赛
function GameDB:getChallengeLevelConf()
    return self:getCachedValues("challengeSeasonRewards")
end

-- 挑战赛
function GameDB:getChallengeLevelInfo(level)
    return self:getCachedValue("challengeSeasonRewards", level)
end

-- 挑战赛
function GameDB:getChallengeInfo(id)
    return self:getCachedValue("challengeGame", id)
end

-- 观察界面统计的数据
function GameDB:getStatisticsInfo()
    return self:getCachedValues("ob_statistics", nil, function(a, b)
        return tonumber(a.ID) < tonumber(b.ID)
    end)
end

-- 根据职业Id返回新手战引导配置
function GameDB:getNewerBattleGuideConfsByClass( class )
    local res = self:getCachedValues("newerBattleGuide",
        function(v)
            return v.class == tostring(class)
        end,
        function(l,r)
            return tonumber(l.ID) < tonumber(r.ID)
        end)
    return res
end

--船长室
function GameDB:getCaptainCollectors()
    local configs = self:getCachedValues("captain_collector")
    return configs 
end

function GameDB:getCaptainLocations()
    local configs = self:getCachedValues("captain_location")
    return configs 
end

function GameDB:getCaptainTalks()
    local configs = self:getCachedValues("captain_actiontalk")
    return configs 
end

-- 充值配置表
function GameDB:getRechargeConfs()
    local configs = self:getCachedValues("recharge")
    return configs 
end

-- 充值配置表
function GameDB:getRechargeForeignConfs()
    local configs = self:getCachedValues("rechargeForeign")
    return configs 
end

function GameDB:getRechargeForeignConfById(id)
    return self:getCachedValue("rechargeForeign", id)
end
--首杀活动
function GameDB:getFirstKillConfigs()
    local configs = self:getCachedValues("dungeon_firstKill")
    return configs 
end

-- 十连抽
function GameDB:getLotteryDropShowById(id)
    local config = self:getCachedValue("activity_tenrand", id)
    if not config then return end
    local lotteryDropList = {}
    local awardShows = string.split(config.awardShow, "#")
    for k, v in ipairs(awardShows) do
        local awardShow = string.split(v, ";")
        if awardShow then
            local typeName = awardShow[1]
            table_remove(awardShow, 1)
            table_insert(lotteryDropList, {name = typeName, dropList = table.concat(awardShow, ";")})
        end
    end
    return lotteryDropList, config.awardShow_string
end

--获取直升礼包数据
function GameDB:getLevelPromotionDataById(id)
    local config = self:getCachedValue("levelpromotion",id)
    return config
end

--直升礼包展示 传入掉落显示这一列
function GameDB:getThroughLvDropShow(dropShowConfig)
    if not dropShowConfig then return end
    local dropList = {}
    local awardShows = string.split(dropShowConfig, "#")
    for k, v in ipairs(awardShows) do
        local awardShow = string.split(v, ";")
        if awardShow then
            local typeName = awardShow[1]
            table_remove(awardShow, 1)
            table_insert(dropList, {name = typeName, dropList = table.concat(awardShow, ";")})
        end
    end
    return dropList
end

-- 翻牌抽奖系统
function GameDB:getShopDrawInfoById(id)
    return self:getCachedValue("activity_rand_type", id)
end

function GameDB:getShopDrawDropShowById(id)
    local config = self:getCachedValue("activity_rand_type", id)
    if not config then return end
    local shopDrawDropList = {}
    if not config.awardShow then return end
    local awardShows = string.split(config.awardShow, "#")
    for k, v in ipairs(awardShows) do
        local awardShow = string.split(v, ";")
        if awardShow then
            local typeName = awardShow[1]
            table_remove(awardShow, 1)         
            table_insert(shopDrawDropList, {name = typeName, dropList = table.concat(awardShow, ";")})
        end
    end
    return shopDrawDropList, config.awardShow_string
end

-- 小额礼包配置
function GameDB:getGiftBagInfoById(id)
    return self:getCachedValue("giftpackage_rmb", id)
end

function GameDB:getDungeonBoxPointById(id)
    return self:getCachedValue("dungeon_boxpoint", id)
end

--地下城boss预览配置 NewTeamBossInfoView
function GameDB:getDungeonBossPreviewConfById(id)
    return self:getCachedValue("dungeon_boss", id)
end

-----------------------------------------------------
-- 解析来源配置 Start
-----------------------------------------------------
--[[
    【把data格式转为resource格式】
    data={ID1;ID2}：  ID1,ID2对应resource表中的ID
    _type：drop类型
    id：这个物品id对应的来源，为了跳转到具体的物品
    param：具体根据funcId来判断
    resource： funcId|str|param;funcId|str|param
]]
function GameDB:getResourceById(id)
    local res = self:getCachedValue("resource", id)
    return res
end

function GameDB:getConvertResource(data, _type, id, subMenu)
    if not data then return end
    local tempResource = {}
    local dataList = string_split(data, ";")
    for i, v in ipairs(dataList) do
        local conf = self:getResourceById(v)
        if conf then
            local param, tempstr

            local funcId = conf.featureonID and tonumber(conf.featureonID) or 0
            local str = conf.name
            local classification = conf.classification_1 and tonumber(conf.classification_1)

            if (funcId >= Constant.FUNC_SHOP_FAME_1 and funcId <= Constant.FUNC_SHOP_FAME_99) 
            or funcId == Constant.FUNC_SHOP_HEROMEDAL 
            or funcId == Constant.FUNC_SHOP_BRIGHTMEDAL 
            or funcId == Constant.FUNC_SHOP_ALLMEDAL 
            or funcId == Constant.FUNC_SHOP_ACHIEVEMENT
            or funcId == Constant.FUNC_TYPE_SHOP
            or funcId == Constant.FUNC_TYPE_CS_SHOP
            or (funcId == Constant.FUNC_TYPE_GANG and classification == 5) 
            or funcId == Constant.FUNC_TYPE_MERCENARY then -- 声望商店/英雄徽章商店/光芒徽章商店/成就商店/商城/公会商店/随从
                param = table_concat({_type, "#", id})
            elseif funcId == Constant.FUNC_TYPE_COMPOUND then -- 制造
                param = self:itemIdTransformFormulaID(_type, id)
            elseif funcId == Constant.FUNC_TYPE_AUCTION_SHOP then -- 拍卖行
                if subMenu then
                    local itemData = UD:parseRewardToBagItem(_type.."|"..id)
                    if itemData then
                        local name = itemData.name
                        param = table_concat({tonumber(subMenu), "#", L(name)})
                    end
                end
            end
            if classification and param then
                tempstr = table_concat({classification, "#", param})
            elseif classification then
                tempstr = classification
            elseif param then
                tempstr = param
            elseif conf.classification_1 then
                tempstr = conf.classification_1
            end
            if tempstr then
                table_insert(tempResource, funcId.."|"..str.."|"..tempstr)
            else
                table_insert(tempResource, funcId.."|"..str)
            end
        end
    end
    if #tempResource > 0 then
        return table_concat(tempResource, ";")
    end
    return nil
end

-- itemID 转为 formulaID
function GameDB:itemIdTransformFormulaID(_type, id)
     local conf = self:getCachedValues("formula")
     if not conf then return end
     local final
     for k,v in pairs(conf) do
         local temp = string_split(v.productShow, "|")
         if temp[1] and temp[2] and tonumber(temp[1]) == _type and tonumber(temp[2]) == id then
             final = tonumber(v.ID)
             break
         end
     end
     return final
end

-- 特殊处理的跳转，任务追踪，NPC跳转等只有一个来源的
function GameDB:getSpecialResource(param)
    if not param then return end
    local res = string.splitTwice(self:getConvertResource(param), {";", "|"}) 
    for _, v in ipairs(res) do
        if v[3] then
            v[3] = string_split(v[3], "#")
        end
    end 
    return res[1]
end

-----------------------------------------------------
-- 解析来源配置 End
-----------------------------------------------------

-- 获得跑马灯配置
function GameDB:getMarqueeConfigById(id)
    return self:getCachedValue("marquee", id)
end

-- 获得某个id推送配置
function GameDB:getPigeonConfById(id)
    return self:getCachedValue("pigeon", id)
end
-- 获得所有推送配置
function GameDB:getPigeonConfs()
    return self:getCachedValues("pigeon", function(v)
        return v.isServer == "0"
    end)
end
-- 获得所有推送配置
function GameDB:getPigeonFreeConfs()
    return self:getCachedValues("pigeon", function(v)
        return v.extraLimit == "0" and v.isServer == "0"
    end)
end

-- 获得强化大师配置
function GameDB:getRecastMasterById(id)
    return self:getCachedValue("enhancer_master", id)
end


--
function GameDB:getResDataByJewelGroupId(id)
    local configs = self:getCachedValues("jewel_group")
    for _, data in ipairs(configs) do
        local values = string.split(data.jewelGroupId, ";")
        for __, value in ipairs(values) do
            if tonumber(value) == id then
                return data
            end
        end
    end
end

----------决斗赛-----------
function GameDB:getDuelRankAwardInfo(myIdx,otherIdx)
    if otherIdx >= myIdx then return 0 end

    local configs = self:getCachedValues("duelGame",nil,function(l,r)
        return tonumber(l.ID) < tonumber(r.ID)
    end)
    local startIdx = 1
    local endIdx = 1
    local temp = {}
    for k,data in ipairs(configs) do
        if myIdx >= tonumber(data.rankingLower) and myIdx < tonumber(data.rankingUpper) then
            startIdx = tonumber(k)
        end

        if otherIdx >= tonumber(data.rankingLower) and otherIdx < tonumber(data.rankingUpper) then
            endIdx = tonumber(k)
            break
        end
    end
    --print(startIdx,endIdx)

    if startIdx == endIdx then
        local info = self:getCachedValue("duelGame",startIdx)
        return tonumber(info.historicalReward) * (myIdx - otherIdx)
    else
        local num = 0
        for i = startIdx, endIdx do
            local info = self:getCachedValue("duelGame",i)
            if i == startIdx then
                num = num + tonumber(info.historicalReward) * (myIdx - tonumber(info.rankingLower))
            elseif i == endIdx then
                num = num + tonumber(info.historicalReward) * (tonumber(info.rankingUpper) - otherIdx)
            else
                num = num + tonumber(info.historicalReward) * (tonumber(info.rankingUpper) - tonumber(info.rankingLower))
            end
        end
        return num
    end
end


-- 付费弹窗
function GameDB:queryActivityOpen()
    local config = self:getCachedValues("activity_open",nil,function(l,r)
        return tonumber(l.ID) < tonumber(r.ID)
    end)
    return config
end

function GameDB:getActivityOpenBySubType(subtype)
    local configs = self:queryActivityOpen()
    for i, v in ipairs(configs) do
        if subtype == tonumber(v.subType) then
            return v
        end
    end
end


function GameDB:getTencentCommunity()
    return self:getCachedValues("tencent_community")
end

function GameDB:getActivityAmazingAwardById(id)
    return self:getCachedValue("activity_amazingaward", id)
end

function GameDB:getNewsPaperEventById(id)
    return self:getCachedValue("newspaper_event", id)
end

function GameDB:getNewsPaperFormatById(id)
    return self:getCachedValue("newspaper_format", id)
end

-- 跨服精英赛
function GameDB:getEliteMatchById(id)
    return self:getCachedValue("elitematch", id)
end

function GameDB:getEliteMatchExp(level, id)
    local level = tostring(level)
    local id = tostring(id)
    return self:getCachedValue("elitematchExp",function(v)
        return v.level==level and v.belong==id
    end)
end

function GameDB:getEliteMatchConfigById(id)
    local config = self:getCachedValues("elitematchConfig",
        function(v)
            return v.belong == tostring(id)
        end,
        function(l,r)
            return tonumber(l.ID) < tonumber(r.ID)
        end)
    return config
end

function GameDB:getEliteMatchShipsById(id)
    return self:getCachedValue("elitematchships", id)
end

function GameDB:getEliteMatchRewardById(id, rank)
    return self:getCachedValue("elitematchReward", function(v)
        local range = string_split(v.rank, "|")
        if v.belong == tostring(id) and rank >= tonumber(range[1]) and rank <= tonumber(range[2]) then
            return v
        end
    end)
end

--英雄宝藏相关
function GameDB:getHeroTreasureByActivityId(activityId)
    local config = self:getCachedValues("activity_battlepass",
        function(v)
            return v.activityId == tostring(activityId)
        end,
        function(l,r)
            return tonumber(l.ID) < tonumber(r.ID)
        end)
    return config
end

--根据活动ID获取英雄宝藏的相关配置
function GameDB:getHeroTreasureConstByActivityId(activityId)
    local config = self:getCachedValue("activity_battlepass_total", activityId)
    return config
end

return GameDB
